/**
 * MIT License
 * 
 * Copyright (c) 2017 CaiDongyu
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.tunnel.client.task;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import com.tunnel.client.udp.UdpData;
import com.tunnel.common.constant.Constant;
import com.tunnel.common.task.BaseTask;
import com.tunnel.common.tunnel.TunnelDataSenderManager;
import com.tunnel.common.util.LogUtil;

import io.netty.channel.ChannelHandlerContext;

/**
 * Tunnel与客户服务之间的通讯任务 在tunnel-client接受到来自tunnel-server的请求之后
 */
public class UdpTask extends BaseTask {

	private UdpData udpData;
	private ChannelHandlerContext ctx;

	public UdpTask(UdpData udpData, ChannelHandlerContext ctx) {
		super();
		this.udpData = udpData;
		this.ctx = ctx;
		this.setName("UdpTask-" + udpData.getIpAndPort());
	}

	@Override
	public void run() {
		DatagramSocket client = null;
    	try {
    		do{
            	/*if(dataLen > 0){
                	LogUtil.d("udp send size["+dataLen+"b]");
            	}*/
            	
            	
            	/*DatagramPacket dataPack = new DatagramPacket(
                        Unpooled.copiedBuffer(udpData.getDatas()),
                        new InetSocketAddress(udpData.getIpAndPort().getIp(), udpData.getIpAndPort().getPort()),
                        new InetSocketAddress("127.0.0.1",5555));
                //netty channel里发送数据是都堆在堆内存里的，空间限制，因此如果写的太快，能回oom
                int waiteMs = 1;
                while(!udpChannel.isWritable()){
                	try {
                		Thread.sleep(waiteMs);
					} catch (Exception e) {}
                	waiteMs = waiteMs+1;
                }
                

                udpChannel.writeAndFlush(dataPack);*/
    			
    			client = new DatagramSocket();
                client.setSoTimeout(1000);//100毫秒
                //封装要发送目标的地址
                InetAddress address = InetAddress.getByName(udpData.getIpAndPort().getIp());
                //封装要发送的DatagramPacket的对象，由于要发送到目的主机，所以要加上地址和端口号
                DatagramPacket sendPacket = new DatagramPacket(udpData.getDataBytes(),udpData.getDataBytes().length,address,udpData.getIpAndPort().getPort());

                try {
                    //发送数据
                    client.send(sendPacket);
                }catch (Exception e){
                    e.printStackTrace();
                }
    			
                byte[] responseBytes = new byte[1024*64];//udp单个数据包最大64k
                //创建响应信息的DatagramPacket对象
                DatagramPacket responsePacket = new DatagramPacket(responseBytes,responseBytes.length);
                client.receive(responsePacket);
                
                //解析数据包内容
                if(responsePacket.getLength() > 0){
                	byte[] data = new byte[responsePacket.getLength()];
                	System.arraycopy(responsePacket.getData(), 0, data, 0, data.length);
//                	LogUtil.d(new String(responsePacket.getData(),0,responsePacket.getLength()));
        			if(ctx != null){
        				TunnelDataSenderManager.commitData(null, TunnelDataSenderManager.UDP_DATA_MSG, ctx, 
        	        			//发送者的地址+分隔符+发送者的端口(占多位)+分隔符+数据
        	        			udpData.getSenderAddressBytes(), Constant.SPLIT_FLAG_BYTES,
        	        			udpData.getSenderPortBytes(), Constant.SPLIT_FLAG_BYTES,
        	        			data);
        			}
                }
                
    		}while(false);
		} catch (Exception e) {
			if(e.getMessage() == null && !e.getMessage().toLowerCase().contains("time out")){
				LogUtil.e(e);
			}
			try {
				if(client != null){
					client.close();
				}
			} catch (Exception e2) {}
		}
	}

	
}
